package imse.team0.processors;

import imse.team0.invoice.PaymentConfirmation;
import imse.team0.orders.Order;
import imse.team0.orders.SplitOrderItem;
import imse.team0.transportation.ShipmentPriceReply;
import org.apache.camel.Body;
import org.apache.camel.Exchange;
import org.apache.camel.Header;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author Eugen, 4/30/12 10:44 PM
 */
public class TemporaryOrderStore {
    private static Map<String, PendingOrder> temporaryOrderStore = new ConcurrentHashMap<String, PendingOrder>();
    private static Map<String, Order> cachedOrderItems = new ConcurrentHashMap<String, Order>();
    private static Map<String, String> cachedTransportationOrders = new ConcurrentHashMap<String, String>();

    private static Logger LOG = LoggerFactory.getLogger(TemporaryOrderStore.class.getName());
    private static Logger RESULT_LOGGER = LoggerFactory.getLogger("imse.team0.results");

    public void putOrder(@Body Order order) {
        PendingOrder pendingOrder = new PendingOrder();
        pendingOrder.order = order;
        temporaryOrderStore.put(order.orderid, pendingOrder);
        LOG.debug("------------->Put order in temp: id=" + order.orderid);
    }

    public void addRemovedId(@Body SplitOrderItem orderItem) {
        PendingOrder pendingOrder = temporaryOrderStore.get(orderItem.orderid);
        pendingOrder.itemIds.add(orderItem.itemId);
        LOG.debug("------------->Added item id for removal in rollback: " + orderItem.itemId);
    }

    public void removeOrder(Exchange ex) {
        String id = ex.getIn().getBody(SplitOrderItem.class).orderid;
        LOG.debug("------------->Removing order with id:" + id);
        PendingOrder pendingOrder = temporaryOrderStore.remove(id);
        ex.getIn().setBody(pendingOrder.order);
        ex.getIn().setHeader("RollbackIDList", pendingOrder.itemIds);
    }

    public void cacheOrder(@Body Order order) {
        LOG.debug("------------->Removing order with id:" + order.orderid + " due to caching");
        PendingOrder pendingOrder = temporaryOrderStore.remove(order.orderid);
        if (pendingOrder == null) {
            LOG.warn("------------->Order with id=" + order.orderid + " was not found in temporary store..");
        }
        cachedOrderItems.put(order.orderid, order);
        LOG.debug("------------->Cached order with id=" + order.orderid);
    }

    public Order retrieveOrder(@Body ShipmentPriceReply reply) {
        Order order = cachedOrderItems.get(reply.getShipmentRequestID());
        if (order == null) {
            LOG.error("(!)----> order with id=" + reply.getShipmentRequestID() + " was not found in cache after transportation agent replied with shipment price");
            throw new RuntimeException("No order found in cache");
        } else {
            LOG.debug("------------->Retrieved order with id=" + order.orderid);
            return order;
        }
    }

    public void cacheTransportationOrder(@Body String jsonRepresentation, @Header("TransportationOrderID") String transportationOrderID) {
        cachedTransportationOrders.put(transportationOrderID, jsonRepresentation);
        LOG.debug("------------->Transportation order with id=" + transportationOrderID + " successfully cached");
    }

    public void removeCachedOrder(@Header("orderID") String orderID) {
        Order order = cachedOrderItems.remove(orderID);
        if (order == null) {
            LOG.error("------------->Customer order with id=" + orderID + " was not found in cache!");
            throw new RuntimeException("Customer order (" +orderID + ") was not found!");
        }
        LOG.debug("-------------> Order id="+orderID+" successfully removed from in-memory cache");
        RESULT_LOGGER.info("-------------> Order id="+orderID+" was successfully processed!");
    }

    public String getAndRemoveTransportationOrder(Exchange exchange) {
        PaymentConfirmation paymentConfirmation = exchange.getIn().getBody(PaymentConfirmation.class);
        String json = cachedTransportationOrders.remove(paymentConfirmation.orderid);
        if (json == null) {
            LOG.error("------------->Transportation order with id=" + paymentConfirmation.orderid + " was not found !");
            throw new RuntimeException("Transportation order (" + paymentConfirmation.orderid + ") not found!");
        }
        LOG.debug("------------->Transportation order with id=" + paymentConfirmation.orderid + " was removed from in-memory store");
        exchange.getIn().setHeader("orderID", paymentConfirmation.orderid);
        return json;
    }


}

class PendingOrder {
    Order order;
    List<String> itemIds = new ArrayList<String>();
}